{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "OccupancyGrid Exploration.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5-2ODPmzclVf",
        "colab_type": "text"
      },
      "source": [
        "## Map import & visualization"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "c5k0J9fw3Y8j",
        "colab_type": "text"
      },
      "source": [
        "### Utils"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BM5jYVgkhLc7",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import os\n",
        "import numpy as np\n",
        "from matplotlib import pyplot as plt"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-UbGABlPElXh",
        "colab_type": "code",
        "outputId": "fb374c9a-8aa7-4068-f507-fb95a583238f",
        "colab": {
          "resources": {
            "http://localhost:8080/nbextensions/google.colab/files.js": {
              "data": "Ly8gQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQwovLwovLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgovLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKLy8KLy8gICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKLy8KLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQovLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAovLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KCi8qKgogKiBAZmlsZW92ZXJ2aWV3IEhlbHBlcnMgZm9yIGdvb2dsZS5jb2xhYiBQeXRob24gbW9kdWxlLgogKi8KKGZ1bmN0aW9uKHNjb3BlKSB7CmZ1bmN0aW9uIHNwYW4odGV4dCwgc3R5bGVBdHRyaWJ1dGVzID0ge30pIHsKICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpOwogIGVsZW1lbnQudGV4dENvbnRlbnQgPSB0ZXh0OwogIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0eWxlQXR0cmlidXRlcykpIHsKICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IHN0eWxlQXR0cmlidXRlc1trZXldOwogIH0KICByZXR1cm4gZWxlbWVudDsKfQoKLy8gTWF4IG51bWJlciBvZiBieXRlcyB3aGljaCB3aWxsIGJlIHVwbG9hZGVkIGF0IGEgdGltZS4KY29uc3QgTUFYX1BBWUxPQURfU0laRSA9IDEwMCAqIDEwMjQ7Ci8vIE1heCBhbW91bnQgb2YgdGltZSB0byBibG9jayB3YWl0aW5nIGZvciB0aGUgdXNlci4KY29uc3QgRklMRV9DSEFOR0VfVElNRU9VVF9NUyA9IDMwICogMTAwMDsKCmZ1bmN0aW9uIF91cGxvYWRGaWxlcyhpbnB1dElkLCBvdXRwdXRJZCkgewogIGNvbnN0IHN0ZXBzID0gdXBsb2FkRmlsZXNTdGVwKGlucHV0SWQsIG91dHB1dElkKTsKICBjb25zdCBvdXRwdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3V0cHV0SWQpOwogIC8vIENhY2hlIHN0ZXBzIG9uIHRoZSBvdXRwdXRFbGVtZW50IHRvIG1ha2UgaXQgYXZhaWxhYmxlIGZvciB0aGUgbmV4dCBjYWxsCiAgLy8gdG8gdXBsb2FkRmlsZXNDb250aW51ZSBmcm9tIFB5dGhvbi4KICBvdXRwdXRFbGVtZW50LnN0ZXBzID0gc3RlcHM7CgogIHJldHVybiBfdXBsb2FkRmlsZXNDb250aW51ZShvdXRwdXRJZCk7Cn0KCi8vIFRoaXMgaXMgcm91Z2hseSBhbiBhc3luYyBnZW5lcmF0b3IgKG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGJyb3dzZXIgeWV0KSwKLy8gd2hlcmUgdGhlcmUgYXJlIG11bHRpcGxlIGFzeW5jaHJvbm91cyBzdGVwcyBhbmQgdGhlIFB5dGhvbiBzaWRlIGlzIGdvaW5nCi8vIHRvIHBvbGwgZm9yIGNvbXBsZXRpb24gb2YgZWFjaCBzdGVwLgovLyBUaGlzIHVzZXMgYSBQcm9taXNlIHRvIGJsb2NrIHRoZSBweXRob24gc2lkZSBvbiBjb21wbGV0aW9uIG9mIGVhY2ggc3RlcCwKLy8gdGhlbiBwYXNzZXMgdGhlIHJlc3VsdCBvZiB0aGUgcHJldmlvdXMgc3RlcCBhcyB0aGUgaW5wdXQgdG8gdGhlIG5leHQgc3RlcC4KZnVuY3Rpb24gX3VwbG9hZEZpbGVzQ29udGludWUob3V0cHV0SWQpIHsKICBjb25zdCBvdXRwdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3V0cHV0SWQpOwogIGNvbnN0IHN0ZXBzID0gb3V0cHV0RWxlbWVudC5zdGVwczsKCiAgY29uc3QgbmV4dCA9IHN0ZXBzLm5leHQob3V0cHV0RWxlbWVudC5sYXN0UHJvbWlzZVZhbHVlKTsKICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5leHQudmFsdWUucHJvbWlzZSkudGhlbigodmFsdWUpID0+IHsKICAgIC8vIENhY2hlIHRoZSBsYXN0IHByb21pc2UgdmFsdWUgdG8gbWFrZSBpdCBhdmFpbGFibGUgdG8gdGhlIG5leHQKICAgIC8vIHN0ZXAgb2YgdGhlIGdlbmVyYXRvci4KICAgIG91dHB1dEVsZW1lbnQubGFzdFByb21pc2VWYWx1ZSA9IHZhbHVlOwogICAgcmV0dXJuIG5leHQudmFsdWUucmVzcG9uc2U7CiAgfSk7Cn0KCi8qKgogKiBHZW5lcmF0b3IgZnVuY3Rpb24gd2hpY2ggaXMgY2FsbGVkIGJldHdlZW4gZWFjaCBhc3luYyBzdGVwIG9mIHRoZSB1cGxvYWQKICogcHJvY2Vzcy4KICogQHBhcmFtIHtzdHJpbmd9IGlucHV0SWQgRWxlbWVudCBJRCBvZiB0aGUgaW5wdXQgZmlsZSBwaWNrZXIgZWxlbWVudC4KICogQHBhcmFtIHtzdHJpbmd9IG91dHB1dElkIEVsZW1lbnQgSUQgb2YgdGhlIG91dHB1dCBkaXNwbGF5LgogKiBAcmV0dXJuIHshSXRlcmFibGU8IU9iamVjdD59IEl0ZXJhYmxlIG9mIG5leHQgc3RlcHMuCiAqLwpmdW5jdGlvbiogdXBsb2FkRmlsZXNTdGVwKGlucHV0SWQsIG91dHB1dElkKSB7CiAgY29uc3QgaW5wdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaW5wdXRJZCk7CiAgaW5wdXRFbGVtZW50LmRpc2FibGVkID0gZmFsc2U7CgogIGNvbnN0IG91dHB1dEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChvdXRwdXRJZCk7CiAgb3V0cHV0RWxlbWVudC5pbm5lckhUTUwgPSAnJzsKCiAgY29uc3QgcGlja2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICBpbnB1dEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKGUpID0+IHsKICAgICAgcmVzb2x2ZShlLnRhcmdldC5maWxlcyk7CiAgICB9KTsKICB9KTsKCiAgY29uc3QgY2FuY2VsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyk7CiAgaW5wdXRFbGVtZW50LnBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoY2FuY2VsKTsKICBjYW5jZWwudGV4dENvbnRlbnQgPSAnQ2FuY2VsIHVwbG9hZCc7CiAgY29uc3QgY2FuY2VsUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICBjYW5jZWwub25jbGljayA9ICgpID0+IHsKICAgICAgcmVzb2x2ZShudWxsKTsKICAgIH07CiAgfSk7CgogIC8vIENhbmNlbCB1cGxvYWQgaWYgdXNlciBoYXNuJ3QgcGlja2VkIGFueXRoaW5nIGluIHRpbWVvdXQuCiAgY29uc3QgdGltZW91dFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gewogICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIHJlc29sdmUobnVsbCk7CiAgICB9LCBGSUxFX0NIQU5HRV9USU1FT1VUX01TKTsKICB9KTsKCiAgLy8gV2FpdCBmb3IgdGhlIHVzZXIgdG8gcGljayB0aGUgZmlsZXMuCiAgY29uc3QgZmlsZXMgPSB5aWVsZCB7CiAgICBwcm9taXNlOiBQcm9taXNlLnJhY2UoW3BpY2tlZFByb21pc2UsIHRpbWVvdXRQcm9taXNlLCBjYW5jZWxQcm9taXNlXSksCiAgICByZXNwb25zZTogewogICAgICBhY3Rpb246ICdzdGFydGluZycsCiAgICB9CiAgfTsKCiAgaWYgKCFmaWxlcykgewogICAgcmV0dXJuIHsKICAgICAgcmVzcG9uc2U6IHsKICAgICAgICBhY3Rpb246ICdjb21wbGV0ZScsCiAgICAgIH0KICAgIH07CiAgfQoKICBjYW5jZWwucmVtb3ZlKCk7CgogIC8vIERpc2FibGUgdGhlIGlucHV0IGVsZW1lbnQgc2luY2UgZnVydGhlciBwaWNrcyBhcmUgbm90IGFsbG93ZWQuCiAgaW5wdXRFbGVtZW50LmRpc2FibGVkID0gdHJ1ZTsKCiAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7CiAgICBjb25zdCBsaSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpJyk7CiAgICBsaS5hcHBlbmQoc3BhbihmaWxlLm5hbWUsIHtmb250V2VpZ2h0OiAnYm9sZCd9KSk7CiAgICBsaS5hcHBlbmQoc3BhbigKICAgICAgICBgKCR7ZmlsZS50eXBlIHx8ICduL2EnfSkgLSAke2ZpbGUuc2l6ZX0gYnl0ZXMsIGAgKwogICAgICAgIGBsYXN0IG1vZGlmaWVkOiAkewogICAgICAgICAgICBmaWxlLmxhc3RNb2RpZmllZERhdGUgPyBmaWxlLmxhc3RNb2RpZmllZERhdGUudG9Mb2NhbGVEYXRlU3RyaW5nKCkgOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbi9hJ30gLSBgKSk7CiAgICBjb25zdCBwZXJjZW50ID0gc3BhbignMCUgZG9uZScpOwogICAgbGkuYXBwZW5kQ2hpbGQocGVyY2VudCk7CgogICAgb3V0cHV0RWxlbWVudC5hcHBlbmRDaGlsZChsaSk7CgogICAgY29uc3QgZmlsZURhdGFQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHsKICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTsKICAgICAgcmVhZGVyLm9ubG9hZCA9IChlKSA9PiB7CiAgICAgICAgcmVzb2x2ZShlLnRhcmdldC5yZXN1bHQpOwogICAgICB9OwogICAgICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoZmlsZSk7CiAgICB9KTsKICAgIC8vIFdhaXQgZm9yIHRoZSBkYXRhIHRvIGJlIHJlYWR5LgogICAgbGV0IGZpbGVEYXRhID0geWllbGQgewogICAgICBwcm9taXNlOiBmaWxlRGF0YVByb21pc2UsCiAgICAgIHJlc3BvbnNlOiB7CiAgICAgICAgYWN0aW9uOiAnY29udGludWUnLAogICAgICB9CiAgICB9OwoKICAgIC8vIFVzZSBhIGNodW5rZWQgc2VuZGluZyB0byBhdm9pZCBtZXNzYWdlIHNpemUgbGltaXRzLiBTZWUgYi82MjExNTY2MC4KICAgIGxldCBwb3NpdGlvbiA9IDA7CiAgICB3aGlsZSAocG9zaXRpb24gPCBmaWxlRGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgIGNvbnN0IGxlbmd0aCA9IE1hdGgubWluKGZpbGVEYXRhLmJ5dGVMZW5ndGggLSBwb3NpdGlvbiwgTUFYX1BBWUxPQURfU0laRSk7CiAgICAgIGNvbnN0IGNodW5rID0gbmV3IFVpbnQ4QXJyYXkoZmlsZURhdGEsIHBvc2l0aW9uLCBsZW5ndGgpOwogICAgICBwb3NpdGlvbiArPSBsZW5ndGg7CgogICAgICBjb25zdCBiYXNlNjQgPSBidG9hKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgY2h1bmspKTsKICAgICAgeWllbGQgewogICAgICAgIHJlc3BvbnNlOiB7CiAgICAgICAgICBhY3Rpb246ICdhcHBlbmQnLAogICAgICAgICAgZmlsZTogZmlsZS5uYW1lLAogICAgICAgICAgZGF0YTogYmFzZTY0LAogICAgICAgIH0sCiAgICAgIH07CiAgICAgIHBlcmNlbnQudGV4dENvbnRlbnQgPQogICAgICAgICAgYCR7TWF0aC5yb3VuZCgocG9zaXRpb24gLyBmaWxlRGF0YS5ieXRlTGVuZ3RoKSAqIDEwMCl9JSBkb25lYDsKICAgIH0KICB9CgogIC8vIEFsbCBkb25lLgogIHlpZWxkIHsKICAgIHJlc3BvbnNlOiB7CiAgICAgIGFjdGlvbjogJ2NvbXBsZXRlJywKICAgIH0KICB9Owp9CgpzY29wZS5nb29nbGUgPSBzY29wZS5nb29nbGUgfHwge307CnNjb3BlLmdvb2dsZS5jb2xhYiA9IHNjb3BlLmdvb2dsZS5jb2xhYiB8fCB7fTsKc2NvcGUuZ29vZ2xlLmNvbGFiLl9maWxlcyA9IHsKICBfdXBsb2FkRmlsZXMsCiAgX3VwbG9hZEZpbGVzQ29udGludWUsCn07Cn0pKHNlbGYpOwo=",
              "ok": true,
              "headers": [
                [
                  "content-type",
                  "application/javascript"
                ]
              ],
              "status": 200,
              "status_text": ""
            }
          },
          "base_uri": "https://localhost:8080/",
          "height": 194
        }
      },
      "source": [
        "from google.colab import files\n",
        "\n",
        "uploaded = files.upload()\n",
        "\n",
        "for fn in uploaded.keys():\n",
        "  print('User uploaded file \"{name}\" with length {length} bytes'.format(\n",
        "      name=fn, length=len(uploaded[fn])))"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "     <input type=\"file\" id=\"files-cc533b48-397f-4bcd-8a8b-1ff1c36e1df5\" name=\"files[]\" multiple disabled />\n",
              "     <output id=\"result-cc533b48-397f-4bcd-8a8b-1ff1c36e1df5\">\n",
              "      Upload widget is only available when the cell has been executed in the\n",
              "      current browser session. Please rerun this cell to enable.\n",
              "      </output>\n",
              "      <script src=\"/nbextensions/google.colab/files.js\"></script> "
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Saving easy_1.npy to easy_1.npy\n",
            "Saving easy_2.npy to easy_2.npy\n",
            "Saving indoor_1.npy to indoor_1.npy\n",
            "User uploaded file \"easy_1.npy\" with length 1280128 bytes\n",
            "User uploaded file \"easy_2.npy\" with length 1280128 bytes\n",
            "User uploaded file \"indoor_1.npy\" with length 1280128 bytes\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RKwbl9mHWois",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# considered_file = list(uploaded.keys())[2]\n",
        "considered_file = 'indoor_1.npy'\n",
        "gmap = np.load('/content/' + considered_file)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aoFnQMwYEm0r",
        "colab_type": "code",
        "outputId": "cb0958f5-d3dd-4ec0-adae-92a41a039b77",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 70
        }
      },
      "source": [
        "grid_resolution = 0.05\n",
        "colormap = plt.get_cmap('jet')\n",
        "\n",
        "color_old_unknown = -1\n",
        "color_old_known = 0\n",
        "color_old_obstacle = 100\n",
        "\n",
        "if colormap == None or colormap.name == 'viridis':\n",
        "  color_unknown = -80\n",
        "  color_known = 0\n",
        "  color_obstacle = 150\n",
        "  color_target = 200\n",
        "  color_robot = -60\n",
        "  color_other = 180\n",
        "elif colormap.name == 'jet':\n",
        "  color_unknown = -100\n",
        "  color_known = -50\n",
        "  color_obstacle = 80\n",
        "  color_target = 1\n",
        "  color_robot = 100\n",
        "  color_other = 30\n",
        "\n",
        "def get_drawable_map(grid, target_pose = None, target_dim = 0.15, robot_pose = None, other_poses = []):\n",
        "\n",
        "    drawable_map = np.copy(grid)\n",
        "    drawable_map[drawable_map == color_old_unknown] = color_unknown # recoloring unknown\n",
        "    drawable_map[drawable_map == color_old_known] = color_known # recoloring known\n",
        "    drawable_map[drawable_map == color_old_obstacle] = color_obstacle # recoloring obstacles\n",
        "    \n",
        "    if other_poses != None and len(other_poses) > 0:\n",
        "      other_dim = 4\n",
        "      for i, pose in enumerate(other_poses):\n",
        "        if(pose != None):\n",
        "          other_x, other_y = odom_to_grid(pose)\n",
        "          cols_index = slice(other_x - (other_dim//2), other_x + (other_dim//2) + 1)\n",
        "          rows_index = slice(other_y - (other_dim//2), other_y + (other_dim//2) + 1)\n",
        "          drawable_map[rows_index, cols_index] = color_other # recoloring other\n",
        "\n",
        "    if robot_pose != None:\n",
        "      robot_dim = 6\n",
        "      robot_x, robot_y = odom_to_grid(robot_pose)\n",
        "      cols_index = slice(robot_x - (robot_dim//2), robot_x + (robot_dim//2) + 1)\n",
        "      rows_index = slice(robot_y - (robot_dim//2), robot_y + (robot_dim//2) + 1)\n",
        "      drawable_map[rows_index, cols_index] = color_robot # recoloring robot\n",
        "      \n",
        "    if target_pose != None:\n",
        "      target_dim = np.maximum(4, np.ceil(target_dim / grid_resolution).astype(int))\n",
        "      target_x, target_y = odom_to_grid(target_pose)\n",
        "      cols_index = slice(target_x - (target_dim//2), target_x + (target_dim//2) + 1)\n",
        "      rows_index = slice(target_y - (target_dim//2), target_y + (target_dim//2) + 1)\n",
        "      drawable_map[rows_index, cols_index] = color_target # recoloring target\n",
        "\n",
        "    return drawable_map\n",
        "\n",
        "\n",
        "def odom_to_grid(odom):\n",
        "    x_grid = round(odom[0] / grid_resolution) + 200\n",
        "    y_grid = round(odom[1] / grid_resolution) + 200\n",
        "    return int(x_grid), int(y_grid)\n",
        "\n",
        "def grid_to_odom(grid):\n",
        "    x_odom = (grid[0] - 200) * grid_resolution\n",
        "    y_odom = (grid[1] - 200) * grid_resolution\n",
        "    return x_odom, y_odom\n",
        "\n",
        "\n",
        "i1, i2 = 0.024, 1.076\n",
        "g1, g2 = odom_to_grid((i1, i2))\n",
        "o1, o2 = grid_to_odom((g1, g2))\n",
        "\n",
        "print('actual \\t', i1, i2)\n",
        "print('grid \\t', g1, g2)\n",
        "print('back \\t', o1, o2)\n",
        "np.testing.assert_allclose(i1, o1, atol=grid_resolution/2)\n",
        "np.testing.assert_allclose(i2, o2, atol=grid_resolution/2)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "actual \t 0.024 1.076\n",
            "grid \t 200 222\n",
            "back \t 0.0 1.1\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rj2ra9FXapc7",
        "colab_type": "code",
        "outputId": "e31e5322-d308-4537-fe70-7ba6299e41b2",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 568
        }
      },
      "source": [
        "plt.figure(figsize = (4,4))\n",
        "plt.grid()\n",
        "plt.title('NOTE: bad color for unknowns and target')\n",
        "plt.imshow(gmap, interpolation='nearest', origin='lower')\n",
        "\n",
        "plt.figure(figsize = (4,5))\n",
        "plt.grid()\n",
        "plt.title('ADJUSTED MAP for ' + considered_file)\n",
        "plt.imshow(get_drawable_map(gmap, (5, 5), 0.4), interpolation='nearest', origin='lower', cmap=colormap)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.image.AxesImage at 0x7f91df960128>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 4
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 288x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 288x360 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LmUgbjjZ3b3r",
        "colab_type": "text"
      },
      "source": [
        "### Demo"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BBXrYaO2LmZc",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# easy1 target (x,y): (0.636197328568,-0.817661881447)\n",
        "# easy2 target (x,y): (2.61609911919,3.43398237228)\n",
        "# easy3 target (x,y): "
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8J_NNdP_XMjn",
        "colab_type": "code",
        "outputId": "c2f7c573-cd48-4b79-c56c-4c943098eb0a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 610
        }
      },
      "source": [
        "plt.figure(figsize = (10,10))\n",
        "plt.grid()\n",
        "tmp_map = get_drawable_map(gmap, target_pose=(-3.8,0), robot_pose=(0,0), other_poses=[(1,1)])\n",
        "plt.imshow(tmp_map, interpolation='nearest', origin='lower', cmap=colormap)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.image.AxesImage at 0x7f91df9f80f0>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 6
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 720x720 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rN2Ke8v3-2z2",
        "colab_type": "text"
      },
      "source": [
        "## Obstacle avoidance"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "toJYKkMt_RVd",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "robot_width = 0.20 # meters\n",
        "\n",
        "\n",
        "def pose_ahead(x, y, theta, meters_ahead = 0.05):\n",
        "  ahead_x = meters_ahead * np.cos(theta) + x\n",
        "  ahead_y = meters_ahead * np.sin(theta) + y\n",
        "  return ahead_x, ahead_y\n",
        "\n",
        "\n",
        "def has_facing_obstacle(grid, x, y, theta, step = grid_resolution, robot_visibility = 1.2, robot_width = 0.20):\n",
        "\n",
        "  obstacle_facing = False\n",
        "  obstacle_distance = None\n",
        "  obstacle_odom = None\n",
        "\n",
        "  adjacent_cells = np.ceil(robot_width/step/2).astype(int)\n",
        "  theta_orthogonal = theta + np.pi/2\n",
        "\n",
        "  for i in range(int(robot_visibility//step)):\n",
        "\n",
        "    distance = step * i\n",
        "    ahead_odom = pose_ahead(x, y, theta, distance)\n",
        "    ahead_grid = odom_to_grid(ahead_odom)\n",
        "\n",
        "    if grid[ahead_grid[::-1]] == 100:\n",
        "      obstacle_facing = True\n",
        "    else:\n",
        "      ahead_grid_near = []\n",
        "      for j in range(1, adjacent_cells + 1):\n",
        "        l = odom_to_grid(pose_ahead(ahead_odom[0], ahead_odom[1], theta_orthogonal, j *  0.05))\n",
        "        r = odom_to_grid(pose_ahead(ahead_odom[0], ahead_odom[1], theta_orthogonal, j * -0.05))\n",
        "        ahead_grid_near.append(l)\n",
        "        ahead_grid_near.append(r)\n",
        "      \n",
        "      ahead_grid_near = list(set(ahead_grid_near))\n",
        "      # print('grid:', ahead_grid, '\\t adj:', ahead_grid_list, '\\t odom:', ahead_odom)\n",
        "\n",
        "      for j in range(len(ahead_grid_near)):\n",
        "        if grid[ahead_grid_near[j][::-1]] == 100: \n",
        "          obstacle_facing = True\n",
        "          break\n",
        "\n",
        "    if obstacle_facing:\n",
        "      obstacle_distance = distance\n",
        "      obstacle_odom = ahead_odom\n",
        "      break\n",
        "\n",
        "  return obstacle_facing, obstacle_distance, obstacle_odom\n",
        "\n",
        "\n",
        "def draw_circle(angle):\n",
        "  fig, ax = plt.subplots()\n",
        "  fig.set_size_inches(3,3)\n",
        "  ax.set_xlim(-1.1,1.1)\n",
        "  ax.set_ylim(-1.1,1.1)\n",
        "  ax.grid()\n",
        "  ax.axhline(y=0, color='k')\n",
        "  ax.axvline(x=0, color='k')\n",
        "  ax.add_patch(plt.Circle((0, 0), 1, color='r', fill=False))\n",
        "  ax.plot(np.cos(angle), np.sin(angle), 'bo')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ut2od5XyDTYC",
        "colab_type": "text"
      },
      "source": [
        "### Random exploration controller\n",
        "\n",
        "The robot sees `robot_visibility` meters in front of itself.\n",
        "\n",
        "- If no obstacle is present in front of the robot, it goes straight ahead until an obstacle is reached.\n",
        "- As soon as an obstacle perfectly facing the robot is reached (also the robot widht is considered here), it will turn around by looking for the best way to follow, computing the best rotation direction based on the distance with obstacles at the left and at the right.\n",
        "- If the robot get stucked in a situation where it cannot avoid the obstacles by just slighlty rotating from its current orientation, then a random `theta` is computed for the next move. \n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "jRzffaf9-6BD",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from IPython.display import clear_output\n",
        "\n",
        "\n",
        "def controller(grid, current_x, current_y, current_theta, step = 0.1, obs_stucked_max = 8):\n",
        "  obs_count = 0\n",
        "\n",
        "  while True:\n",
        "    clear_output(wait=True)\n",
        "\n",
        "    # draw current situation\n",
        "    draw_circle(current_theta)\n",
        "    obs_present, obs_dist, obs_odom = has_facing_obstacle(grid, current_x, current_y, current_theta)\n",
        "    plt.figure(figsize = (10,10))\n",
        "    plt.grid()\n",
        "    plt.imshow(get_drawable_map(grid, target_pose=(5,7), robot_pose=(current_x, current_y), other_poses=[obs_odom]), interpolation='nearest', origin='lower', cmap=colormap)\n",
        "    plt.pause(0.3)\n",
        "\n",
        "    if(not obs_present): # movement ahead\n",
        "      obs_count = 0\n",
        "      current_x, current_y = pose_ahead(current_x, current_y, current_theta, meters_ahead=step) # publish linear velocity here\n",
        "\n",
        "    else: # look for a free path by turning around\n",
        "      obs_count += 1\n",
        "      if obs_count > obs_stucked_max: # prevent the robot to be stucked in trying the same orientations over and over\n",
        "        current_theta += np.deg2rad(np.random.uniform(-130, 130))\n",
        "\n",
        "      # evaluating left and right side of the robot to choose the turning direction\n",
        "      left_distances = []\n",
        "      right_distances = []\n",
        "      for i in range(1, 45, 5):\n",
        "        _, dist_left, _ = has_facing_obstacle(grid, current_x, current_y, current_theta + np.deg2rad(i), robot_visibility=2.)\n",
        "        _, dist_right, _ = has_facing_obstacle(grid, current_x, current_y, current_theta - np.deg2rad(i), robot_visibility=2.)\n",
        "        left_distances.append(dist_left or 4)\n",
        "        right_distances.append(dist_right or 4)\n",
        "\n",
        "      # once both sides are evaluated, the robot tries to turn the preferred way for finding a free path\n",
        "      previous_obs_dist = 0\n",
        "      deg_delta = 5 if np.mean(left_distances) > np.mean(right_distances) else -5\n",
        "      while obs_present and obs_dist * 1.8 >= previous_obs_dist: # allows to take still-blocked ways that are better than before\n",
        "        previous_obs_dist = obs_dist\n",
        "        current_theta += np.deg2rad(deg_delta) # step-by-step research (could be improved by adding decay on `deg_delta`)\n",
        "        obs_present, obs_dist, obs_odom = has_facing_obstacle(grid, current_x, current_y, current_theta)\n",
        "\n",
        "\n",
        "\n",
        "\n",
        "start_x, start_y = 0, 1\n",
        "start_theta = np.pi/2\n",
        "\n",
        "controller(gmap, start_x, start_y, start_theta)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pJA3BJlBdIuN",
        "colab_type": "text"
      },
      "source": [
        "## Path Planning"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PhW7Hgq_I_nN",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import math\n",
        "\n",
        "def euclidean_distance_tuple(current_pose, target_pose):\n",
        "  return math.sqrt(math.pow((target_pose[0] - current_pose[0]), 2) +\n",
        "\t\t\t\t\t          math.pow((target_pose[1] - current_pose[1]), 2))\n",
        "\n",
        "\n",
        "class GraphNode:\n",
        "  def __init__(self, pose, g_score, prev_node_pose, goal_pose):\n",
        "    self.pose = pose\n",
        "    self.g_score = g_score # actual cost\n",
        "    self.h_score = 0 if goal_pose == None else euclidean_distance_tuple(self.pose, goal_pose) # heuristic cost\n",
        "    self.prev_node_pose = prev_node_pose\n",
        "\n",
        "  def f_score(self):\n",
        "    return self.g_score + self.h_score # priority cost\n",
        "\n",
        "  def __str__(self):\n",
        "    return str(self.pose) + \", g:\" + str(self.g_score) + \", f:\" + \"{:.3f}\".format(self.f_score()) + \", prev:\" + str(self.prev_node_pose)\n",
        "\n",
        "\n",
        "\n",
        "def get_neighbourhood(grid, grid_pose, robot_width=0.20, grid_resolution=0.05):\n",
        "\n",
        "  # due to the robot width, cells next to the obstacles must be ignored\n",
        "  collision_cells = np.ceil(robot_width/grid_resolution/2).astype(int)\n",
        "\n",
        "  nrows = grid.shape[0]\n",
        "  ncols = grid.shape[1]\n",
        "  row = grid_pose[1] # y=row\n",
        "  col = grid_pose[0] # x=col\n",
        "  neighbourhood = []\n",
        "\n",
        "  # When reading this code, please remember that while pose is expressed as (X,Y),\n",
        "  # the matrix indexing for `grid` is instead to be done as (Y,X).\n",
        "  # Moreover, the Y is flipped in the map (see images above), then for moving the\n",
        "  # robot UP we actually need to increment Y (rows index + 1)\n",
        "  # instead of decreasing it (such as it would happen in a normal matrix).\n",
        "\n",
        "  if col > 0 and grid[row, col - min(col, collision_cells)] != color_old_obstacle:\n",
        "    neighbourhood.append((col - 1, row)) # left\n",
        "  if col < ncols - 1 and grid[row, col + min(ncols - col - 1, collision_cells)] != color_old_obstacle:\n",
        "    neighbourhood.append((col + 1, row)) # right\n",
        "\n",
        "  if row > 0 and grid[row - min(row, collision_cells), col] != color_old_obstacle:\n",
        "    neighbourhood.append((col, row - 1)) # down\n",
        "  if row < nrows - 1 and grid[row + min(nrows - row - 1, collision_cells), col] != color_old_obstacle:\n",
        "    neighbourhood.append((col, row + 1)) # up\n",
        "\n",
        "  if col > 0 and row > 0 and grid[row - min(row, collision_cells), col - min(col, collision_cells)] != color_old_obstacle:\n",
        "    neighbourhood.append((col - 1, row - 1)) # diagonal left-down\n",
        "  if col > 0 and row < nrows - 1 and grid[row - min(nrows - row - 1, collision_cells), col - min(col, collision_cells)] != color_old_obstacle:\n",
        "    neighbourhood.append((col - 1, row + 1)) # diagonal left-up\n",
        "\n",
        "  if col < ncols - 1 and row > 0 and grid[row - min(row, collision_cells), col + min(ncols - col - 1, collision_cells)] != color_old_obstacle:\n",
        "    neighbourhood.append((col + 1, row - 1)) # diagonal right-down\n",
        "  if col < ncols - 1 and row < nrows - 1 and grid[row + min(nrows - row - 1, collision_cells), col + min(ncols - col - 1, collision_cells)] != color_old_obstacle:\n",
        "    neighbourhood.append((col + 1, row + 1)) # diagonal right-up\n",
        "\n",
        "  # print(grid_pose, neighbourhood)\n",
        "  return neighbourhood\n",
        "\n",
        "\n",
        "def get_complete_path(nodes_set, node):\n",
        "  path = [node.pose]\n",
        "  while node.prev_node_pose != None:\n",
        "    path.append(node.prev_node_pose)\n",
        "    node = nodes_set[node.prev_node_pose]\n",
        "  return path[::-1]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EvixDgokTaOe",
        "colab_type": "text"
      },
      "source": [
        "### A* and Dijkstra algorithms"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VNw6qmUOTYAe",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def path_planning(grid, start_odom, goal_odom, goal_color = None):\n",
        "  # Applies A* or Dijkstra depending on the fact that `goal_odom` is specified or not\n",
        "\n",
        "  start_grid = odom_to_grid(start_odom)\n",
        "  goal_grid = None if goal_odom == None else odom_to_grid(goal_odom)\n",
        "  \n",
        "  if goal_grid == None and goal_color == None: \n",
        "    raise Exception('You must have either a goal pose or color.')\n",
        "\n",
        "  open_set = dict() # nodes to explore\n",
        "  closed_set = dict() # already explored nodes\n",
        "  \n",
        "  start_node = GraphNode(start_grid, 0, None, goal_grid)\n",
        "  open_set[start_node.pose] = start_node\n",
        "\n",
        "\n",
        "  while len(open_set) > 0:\n",
        "\n",
        "    # get the node with minimum f_score\n",
        "    chosen_idx = min(open_set, key = lambda dict_idx: open_set[dict_idx].f_score()) \n",
        "    current_node = open_set[chosen_idx]\n",
        "    \n",
        "    success = True if goal_grid == None or current_node.pose == goal_grid else False\n",
        "    success = True if success and (goal_color == None or grid[current_node.pose[::-1]] == goal_color) else False\n",
        "\n",
        "    if success: \n",
        "      return [grid_to_odom(p) for p in get_complete_path(closed_set, current_node)] # success: goal reached\n",
        "\n",
        "    del open_set[chosen_idx]\n",
        "    closed_set[chosen_idx] = current_node\n",
        "\n",
        "    neighbourhood = get_neighbourhood(grid, current_node.pose) # list of neighbours poses (tuple)\n",
        "    \n",
        "    for i, neighbour in enumerate(neighbourhood):\n",
        "      \n",
        "      if neighbour in closed_set:\n",
        "          continue # already explored\n",
        "\n",
        "      g_score = current_node.g_score + euclidean_distance_tuple(current_node.pose, neighbour)\n",
        "\n",
        "      if neighbour not in open_set: # new node\n",
        "          open_set[neighbour] = GraphNode(neighbour, g_score, current_node.pose, goal_grid)\n",
        "      \n",
        "      elif open_set[neighbour].g_score > g_score: # best path for reaching the node `neighbour` \n",
        "              open_set[neighbour].g_score = g_score\n",
        "              open_set[neighbour].prev_node_pose = current_node.pose\n",
        "\n",
        "  return None # failure: open_set is empty but goal was never reached"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0W9a2xNvdPMV",
        "colab_type": "text"
      },
      "source": [
        "### Goal reaching"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LZUGlksnDY2p",
        "colab_type": "code",
        "outputId": "728c11af-acd6-4673-f1d7-fcc51694b3b4",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 701
        }
      },
      "source": [
        "ip = (0,1)\n",
        "gp = (-3,1)\n",
        "result = path_planning(gmap, ip, gp)\n",
        "print('Init pose: ', ip)\n",
        "print('Goal pose: ', gp)\n",
        "print('Path plan: ', result)\n",
        "print('Path length: ', len(result) if result != None else 0)\n",
        "\n",
        "plt.figure(figsize = (10,10))\n",
        "plt.grid()\n",
        "plt.imshow(get_drawable_map(gmap, target_pose=gp, robot_pose=ip, other_poses=result), interpolation='nearest', origin='lower', cmap=colormap)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Init pose:  (0, 1)\n",
            "Goal pose:  (-3, 1)\n",
            "Path plan:  [(0.0, 1.0), (-0.05, 0.9500000000000001), (-0.1, 0.9), (-0.15000000000000002, 0.8500000000000001), (-0.2, 0.8), (-0.25, 0.75), (-0.30000000000000004, 0.7000000000000001), (-0.35000000000000003, 0.65), (-0.4, 0.6000000000000001), (-0.45, 0.55), (-0.5, 0.5), (-0.55, 0.45), (-0.6000000000000001, 0.4), (-0.65, 0.35000000000000003), (-0.65, 0.30000000000000004), (-0.7000000000000001, 0.25), (-0.75, 0.2), (-0.8, 0.15000000000000002), (-0.8500000000000001, 0.2), (-0.9, 0.15000000000000002), (-0.9500000000000001, 0.2), (-1.0, 0.25), (-1.05, 0.30000000000000004), (-1.1, 0.35000000000000003), (-1.1500000000000001, 0.4), (-1.2000000000000002, 0.45), (-1.25, 0.5), (-1.3, 0.55), (-1.35, 0.6000000000000001), (-1.4000000000000001, 0.65), (-1.4500000000000002, 0.7000000000000001), (-1.5, 0.75), (-1.55, 0.8), (-1.6, 0.8500000000000001), (-1.6500000000000001, 0.9), (-1.7000000000000002, 0.9500000000000001), (-1.75, 1.0), (-1.8, 1.05), (-1.85, 1.1), (-1.9000000000000001, 1.1500000000000001), (-1.9500000000000002, 1.2000000000000002), (-2.0, 1.25), (-2.0500000000000003, 1.3), (-2.1, 1.35), (-2.15, 1.4000000000000001), (-2.2, 1.4500000000000002), (-2.25, 1.4500000000000002), (-2.3000000000000003, 1.5), (-2.3000000000000003, 1.55), (-2.3000000000000003, 1.6), (-2.35, 1.6), (-2.4000000000000004, 1.6), (-2.45, 1.6), (-2.5, 1.6), (-2.5500000000000003, 1.55), (-2.6, 1.5), (-2.6500000000000004, 1.4500000000000002), (-2.7, 1.4000000000000001), (-2.75, 1.35), (-2.8000000000000003, 1.3), (-2.85, 1.25), (-2.9000000000000004, 1.2000000000000002), (-2.95, 1.1500000000000001), (-2.95, 1.1), (-2.95, 1.05), (-3.0, 1.0)]\n",
            "Path length:  66\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.image.AxesImage at 0x7f91db5d4cf8>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 70
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 720x720 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JpZWR3w8Iz_3",
        "colab_type": "text"
      },
      "source": [
        "### Looking for unknown areas"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3WC0TZGLKyy0",
        "colab_type": "code",
        "outputId": "7eafaa4a-3ae8-4409-e45c-1f2fb30b1f72",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 683
        }
      },
      "source": [
        "ip = (0.5,-0.5)\n",
        "result = path_planning(gmap, ip, None, -1)\n",
        "print('Init pose: ', ip)\n",
        "print('Path plan: ', result)\n",
        "print('Path length: ', len(result) if result != None else 0)\n",
        "\n",
        "plt.figure(figsize = (10,10))\n",
        "plt.grid()\n",
        "plt.imshow(get_drawable_map(gmap, target_pose=gp, robot_pose=ip, other_poses=result), interpolation='nearest', origin='lower', cmap=colormap)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Init pose:  (0.5, -0.5)\n",
            "Path plan:  [(0.5, -0.5), (0.45, -0.5), (0.4, -0.5), (0.35000000000000003, -0.5), (0.30000000000000004, -0.5), (0.25, -0.5), (0.2, -0.5), (0.15000000000000002, -0.55), (0.1, -0.6000000000000001), (0.05, -0.6000000000000001), (0.0, -0.6000000000000001), (-0.05, -0.6000000000000001), (-0.1, -0.6000000000000001), (-0.15000000000000002, -0.6000000000000001), (-0.2, -0.6000000000000001), (-0.25, -0.6000000000000001), (-0.30000000000000004, -0.65), (-0.35000000000000003, -0.65), (-0.4, -0.65), (-0.45, -0.65), (-0.5, -0.65), (-0.55, -0.65), (-0.6000000000000001, -0.65), (-0.65, -0.65), (-0.7000000000000001, -0.65), (-0.75, -0.65), (-0.8, -0.65), (-0.8500000000000001, -0.65), (-0.9, -0.65), (-0.9500000000000001, -0.65), (-1.0, -0.65), (-1.05, -0.7000000000000001), (-1.1, -0.75), (-1.1500000000000001, -0.8), (-1.2000000000000002, -0.8500000000000001), (-1.25, -0.9), (-1.3, -0.9500000000000001), (-1.35, -1.0), (-1.4000000000000001, -1.05), (-1.4500000000000002, -1.1), (-1.4500000000000002, -1.1500000000000001), (-1.4500000000000002, -1.2000000000000002), (-1.4500000000000002, -1.25), (-1.4000000000000001, -1.3), (-1.35, -1.35), (-1.3, -1.4000000000000001)]\n",
            "Path length:  46\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.image.AxesImage at 0x7f91db2d9a90>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 79
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 720x720 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uJsBZ3GWVlcS",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}